// 性能基准测试

import { RedisToolkit } from '../src';

interface BenchmarkResult {
  operation: string;
  totalOperations: number;
  totalTime: number;
  operationsPerSecond: number;
  averageLatency: number;
  minLatency: number;
  maxLatency: number;
}

class Benchmark {
  private redis: RedisToolkit;
  private results: BenchmarkResult[] = [];

  constructor() {
    this.redis = new RedisToolkit({
      host: process.env['REDIS_HOST'] || 'localhost',
      port: parseInt(process.env['REDIS_PORT'] || '6379'),
      autoSerialize: true,
    });
  }

  async run(): Promise<void> {
    console.log('🚀 开始Redis Toolkit性能基准测试...\n');

    try {
      await this.redis.connect();
      console.log('✅ Redis连接成功\n');

      // 运行各种基准测试
      await this.benchmarkCache();
      await this.benchmarkCounter();
      await this.benchmarkQueue();
      await this.benchmarkLeaderboard();
      await this.benchmarkRateLimit();
      await this.benchmarkLock();
      await this.benchmarkSet();
      await this.benchmarkBloomFilter();

      // 显示结果
      this.displayResults();

    } catch (error) {
      console.error('❌ 基准测试失败:', error);
    } finally {
      await this.redis.disconnect();
      console.log('📡 Redis连接已断开');
    }
  }

  private async benchmarkCache(): Promise<void> {
    console.log('🗄️ 缓存性能测试...');

    // 缓存写入测试
    await this.runBenchmark('Cache Set', 1000, async (i) => {
      await this.redis.cache.set(`cache-test-${i}`, { id: i, data: `test-data-${i}` });
    });

    // 缓存读取测试
    await this.runBenchmark('Cache Get', 1000, async (i) => {
      await this.redis.cache.get(`cache-test-${i}`);
    });

    // 批量操作测试
    await this.runBenchmark('Cache Batch Set', 100, async (i) => {
      const promises = Array.from({ length: 10 }, (_, j) =>
        this.redis.cache.set(`batch-${i}-${j}`, { batch: i, item: j }, { ttl: 300 })
      );
      await Promise.all(promises);
    });

    console.log('✅ 缓存性能测试完成\n');
  }

  private async benchmarkCounter(): Promise<void> {
    console.log('🔢 计数器性能测试...');

    // 计数器增量测试
    await this.runBenchmark('Counter Increment', 1000, async (i) => {
      await this.redis.counter.increment(`counter-test-${i % 10}`, 1);
    });

    // 时间窗口计数测试
    await this.runBenchmark('Window Counter', 500, async (i) => {
      await this.redis.counter.incrementWindow(`window-counter-${i % 5}`, 3600, 1);
    });

    console.log('✅ 计数器性能测试完成\n');
  }

  private async benchmarkQueue(): Promise<void> {
    console.log('📋 队列性能测试...');

    // 队列添加测试
    await this.runBenchmark('Queue Add Job', 1000, async (i) => {
      await this.redis.queue.addJob('benchmark-queue', {
        type: 'benchmark-job',
        payload: { id: i, timestamp: Date.now() }
      });
    });

    // 队列处理测试
    await this.runBenchmark('Queue Get Job', 500, async () => {
      await this.redis.queue.getJob('benchmark-queue');
    });

    console.log('✅ 队列性能测试完成\n');
  }

  private async benchmarkLeaderboard(): Promise<void> {
    console.log('🏆 排行榜性能测试...');

    // 分数更新测试
    await this.runBenchmark('Leaderboard Update', 1000, async (i) => {
      await this.redis.leaderboard.updateScore('benchmark-leaderboard', `player-${i}`, Math.random() * 1000);
    });

    // 排行榜查询测试
    await this.runBenchmark('Leaderboard Query', 200, async () => {
      await this.redis.leaderboard.getTopN('benchmark-leaderboard', 10);
    });

    console.log('✅ 排行榜性能测试完成\n');
  }

  private async benchmarkRateLimit(): Promise<void> {
    console.log('⏱️ 限流性能测试...');

    // 固定窗口限流测试
    await this.runBenchmark('Rate Limit Check', 1000, async (i) => {
      await this.redis.rateLimit.checkFixedWindow(`rate-limit-${i % 10}`, 100, 60);
    });

    console.log('✅ 限流性能测试完成\n');
  }

  private async benchmarkLock(): Promise<void> {
    console.log('🔒 分布式锁性能测试...');

    // 锁获取和释放测试
    await this.runBenchmark('Lock Acquire/Release', 200, async (i) => {
      const token = await this.redis.lock.acquire(`lock-test-${i % 5}`, { ttl: 10 });
      if (token) {
        await this.redis.lock.release(`lock-test-${i % 5}`, token);
      }
    });

    console.log('✅ 分布式锁性能测试完成\n');
  }

  private async benchmarkSet(): Promise<void> {
    console.log('📦 集合性能测试...');

    // 集合添加测试
    await this.runBenchmark('Set Add', 1000, async (i) => {
      await this.redis.set.add(`set-test-${i % 10}`, `member-${i}`);
    });

    // 有序集合测试
    await this.runBenchmark('Sorted Set Add', 1000, async (i) => {
      await this.redis.set.addScored(`zset-test-${i % 10}`, Math.random() * 1000, `member-${i}`);
    });

    console.log('✅ 集合性能测试完成\n');
  }

  private async benchmarkBloomFilter(): Promise<void> {
    console.log('🌸 布隆过滤器性能测试...');

    // 创建布隆过滤器
    const filterName = `bloom-benchmark-${Date.now()}`;
    await this.redis.bloom.create(filterName, { capacity: 10000, errorRate: 0.01 });

    // 布隆过滤器添加测试
    await this.runBenchmark('Bloom Filter Add', 1000, async (i) => {
      await this.redis.bloom.add(filterName, `element-${i}`);
    });

    // 布隆过滤器检查测试
    await this.runBenchmark('Bloom Filter Check', 1000, async (i) => {
      await this.redis.bloom.mightContain(filterName, `element-${i}`);
    });

    // 清理
    await this.redis.bloom.delete(filterName);

    console.log('✅ 布隆过滤器性能测试完成\n');
  }

  private async runBenchmark(
    operation: string,
    iterations: number,
    testFunction: (i: number) => Promise<void>
  ): Promise<void> {
    const latencies: number[] = [];
    const startTime = Date.now();

    for (let i = 0; i < iterations; i++) {
      const operationStart = Date.now();
      await testFunction(i);
      const operationEnd = Date.now();
      latencies.push(operationEnd - operationStart);
    }

    const endTime = Date.now();
    const totalTime = endTime - startTime;
    const operationsPerSecond = (iterations / totalTime) * 1000;
    const averageLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length;
    const minLatency = Math.min(...latencies);
    const maxLatency = Math.max(...latencies);

    const result: BenchmarkResult = {
      operation,
      totalOperations: iterations,
      totalTime,
      operationsPerSecond,
      averageLatency,
      minLatency,
      maxLatency,
    };

    this.results.push(result);

    console.log(`  ${operation}: ${operationsPerSecond.toFixed(0)} ops/sec (avg: ${averageLatency.toFixed(2)}ms)`);
  }

  private displayResults(): void {
    console.log('\n📊 基准测试结果汇总:');
    console.log('=' .repeat(80));
    console.log('操作'.padEnd(25) + 
                '总操作数'.padEnd(10) + 
                'ops/sec'.padEnd(12) + 
                '平均延迟'.padEnd(10) + 
                '最小延迟'.padEnd(10) + 
                '最大延迟');
    console.log('-'.repeat(80));

    for (const result of this.results) {
      console.log(
        result.operation.padEnd(25) +
        result.totalOperations.toString().padEnd(10) +
        result.operationsPerSecond.toFixed(0).padEnd(12) +
        `${result.averageLatency.toFixed(2)}ms`.padEnd(10) +
        `${result.minLatency}ms`.padEnd(10) +
        `${result.maxLatency}ms`
      );
    }

    console.log('-'.repeat(80));

    // 计算总体统计
    const totalOps = this.results.reduce((sum, r) => sum + r.totalOperations, 0);
    const totalTime = this.results.reduce((sum, r) => sum + r.totalTime, 0);
    const avgOpsPerSec = this.results.reduce((sum, r) => sum + r.operationsPerSecond, 0) / this.results.length;

    console.log(`\n📈 总体统计:`);
    console.log(`  总操作数: ${totalOps.toLocaleString()}`);
    console.log(`  总耗时: ${(totalTime / 1000).toFixed(2)}秒`);
    console.log(`  平均吞吐量: ${avgOpsPerSec.toFixed(0)} ops/sec`);

    // 性能评级
    console.log(`\n🎯 性能评级:`);
    if (avgOpsPerSec > 5000) {
      console.log('  🚀 优秀 - 高性能Redis操作');
    } else if (avgOpsPerSec > 2000) {
      console.log('  ✅ 良好 - 性能表现正常');
    } else if (avgOpsPerSec > 1000) {
      console.log('  ⚠️  一般 - 性能可以优化');
    } else {
      console.log('  ❌ 较差 - 需要性能优化');
    }

    console.log('\n💡 优化建议:');
    console.log('  - 使用连接池提高并发性能');
    console.log('  - 启用管道(Pipeline)进行批量操作');
    console.log('  - 考虑使用Redis集群提高吞吐量');
    console.log('  - 优化网络延迟和Redis服务器配置');
  }
}

// 运行基准测试
async function runBenchmark() {
  const benchmark = new Benchmark();
  await benchmark.run();
}

if (require.main === module) {
  runBenchmark().catch(console.error);
}

export { Benchmark, runBenchmark };
